package com.libre.workflow.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.libre.auth.entity.User;
import com.libre.auth.service.UserService;
import com.libre.common.exception.BusinessRuntimeException;
import com.libre.common.utils.DateTimeUtil;
import com.libre.common.utils.StringUtil;
import com.libre.common.vo.PageVo;
import com.libre.workflow.service.MyModelService;
import com.libre.workflow.vo.MyModelVo;
import com.google.common.collect.Lists;
import org.flowable.bpmn.exceptions.XMLException;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.ui.common.security.SecurityUtils;
import org.flowable.ui.modeler.model.ModelKeyRepresentation;
import org.flowable.ui.modeler.model.ModelRepresentation;
import org.flowable.ui.modeler.repository.ModelRepository;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.flowable.ui.modeler.domain.Model;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class MyModelServiceImpl implements MyModelService {

    @Autowired
    UserService userService;
    @Autowired
    ModelService modelService;
    @Autowired
    ModelRepository modelRepository;
    @Autowired
    RepositoryService repositoryService;

    @Override
    public Page findPage(PageVo pageVo, MyModelVo modelVo) {
        int size = pageVo.getPageSize();
        int current = pageVo.getPageNumber();
        int fromIndex = (current - 1) * size;// 每页多少条
        int toIndex = current * size;// 每页多少条
        List<Model> modelList = modelRepository.findByModelType(modelVo.getModelType(), modelVo.getSort());
        List<Model> models = Lists.newArrayList();
        // 通过名字过滤
        if (StringUtil.isNotEmpty(modelVo.getName())) {
            models = modelList.stream().filter(it -> it.getName().indexOf(modelVo.getName()) != -1).collect(Collectors.toList());
        } else {
            models = modelList;
        }
        int count = models.size();
        System.out.println("模型总数量：" + count);
        if (toIndex > count) {
            toIndex = count;
        }
        List<Model> records = models.subList(fromIndex, toIndex);
        JSONArray arr = new JSONArray();
        //查询所有用户信息
        List<User> allUsers = userService.list();
        for (Model model : records) {
            JSONObject obj = new JSONObject();
            obj.put("id", model.getId());
            obj.put("name", model.getName());
            obj.put("key", model.getKey());
            obj.put("description", model.getDescription());
            obj.put("created", DateTimeUtil.format(model.getCreated(), DateTimeUtil.DATE_TIME));//创建时间
            obj.put("lastUpdated", DateTimeUtil.format(model.getLastUpdated(), DateTimeUtil.DATE_TIME));//最后更新时间
            //创建人
            User user = allUsers.stream().filter(u -> (u.getId()).equals(model.getCreatedBy())).findAny().orElse(null);
            if (user != null) {
                obj.put("createdBy", model.getCreatedBy());//创建人ID
                obj.put("createdByName", user.getRealName());//创建人
            } else {
                obj.put("createdBy", model.getCreatedBy());//创建人ID
                obj.put("createdByName", null);//创建人
            }
            //更新人
            User user1 = allUsers.stream().filter(u -> (u.getId()).equals(model.getCreatedBy())).findAny().orElse(null);
            if (user1 != null) {
                obj.put("lastUpdatedBy", model.getLastUpdatedBy());//最后更新人ID
                obj.put("lastUpdatedByName", user1.getRealName());//最后更新人
            } else {
                obj.put("lastUpdatedBy", model.getLastUpdatedBy());//最后更新人ID
                obj.put("lastUpdatedByName", null);//最后更新人
            }
            obj.put("version", model.getVersion());
            obj.put("modelEditorJson", model.getModelEditorJson());
            obj.put("comment", model.getComment());
            obj.put("modelType", model.getModelType());
            obj.put("tenantId", model.getTenantId());
            arr.add(obj);
        }
        Page page = new Page(current, size, count);
        page.setRecords(arr);
        page.setTotal(count);
        return page;
    }

    @Override
    public ModelRepresentation createModel(ModelRepresentation modelRepresentation) {
        modelRepresentation.setKey(modelRepresentation.getKey().replaceAll(" ", ""));
        ModelKeyRepresentation modelKeyInfo = modelService.validateModelKey(null, modelRepresentation.getModelType(), modelRepresentation.getKey());
        if (modelKeyInfo.isKeyAlreadyExists()) {
//            throw new ConflictingRequestException("模型的KEY已经存在: " + modelRepresentation.getKey() + ",不能重复创建");
            throw new BusinessRuntimeException("模型的KEY已经存在: " + modelRepresentation.getKey() + ",不能重复创建");
        }
        String json = modelService.createModelJson(modelRepresentation);
        Model newModel = modelService.createModel(modelRepresentation, json, SecurityUtils.getCurrentUserObject());
        ModelRepresentation model = new ModelRepresentation(newModel);
        return model;
    }

    @Override
    public void deploy(String id) throws Exception {
        //获取模型
        Model modelData = modelService.getModel(id);
        byte[] bytes = modelService.getBpmnXML(modelData);
        if (bytes == null) {
            throw new BusinessRuntimeException("模型数据为空，请先设计流程并成功保存，再进行发布。");
        }
        BpmnModel model = modelService.getBpmnModel(modelData);
        if (model.getProcesses().size() == 0) {
            throw new BusinessRuntimeException("数据模型不符要求，请至少设计一条主线流程。");
        }
        byte[] bpmnBytes = modelService.getBpmnXML(modelData);
        //发布流程
        String processName = modelData.getName() + ".bpmn20.xml";
        Deployment deployment = null;
        try {
            deployment = repositoryService.createDeployment()
                    .name(modelData.getName())
                    .addString(processName, new String(bpmnBytes, "UTF-8"))
                    .deploy();
        } catch (XMLException e) {
            throw new BusinessRuntimeException("绘制流程图异常，请检查后重新发布");
        }
        Model model1 = modelService.saveModel(modelData);
    }

    @Override
    public void delete(String id) {
        modelService.deleteModel(id);
    }

}
